package net.goutalk.glcs.module.authority.utils;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import net.goutalk.glcs.common.constant.GlobalConstant;
import net.goutalk.glcs.common.enums.DataAuthFieldTypeEnum;
import net.goutalk.glcs.common.enums.DataAuthMethodEnum;
import net.goutalk.glcs.common.enums.DataAuthScopeEnum;
import net.goutalk.glcs.common.enums.DataAuthTypeEnum;
import net.goutalk.glcs.common.utils.RedisUtil;
import net.goutalk.glcs.module.authority.entity.DataAuth;
import net.goutalk.glcs.module.authority.entity.DataAuthConfig;
import net.goutalk.glcs.module.authority.entity.DataAuthRelation;
import net.goutalk.glcs.module.authority.entity.DataAuthTableRelation;
import net.goutalk.glcs.module.organization.entity.*;
import lombok.SneakyThrows;
import net.goutalk.glcs.module.organization.entity.*;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 数据权限工具类
 *
 * @Author: tanyujie
 * @Date: 2023/3/1 10:22
 */
public class AuthorityUtil {

    static RedisUtil redisUtil;

    static {
        redisUtil = SpringUtil.getBean(RedisUtil.class);
    }

    /**
     * 根据表名 获取表达式解析
     *
     * @param tableName  表名
     * @param tableAlias 表别名
     * @return
     */
    public static Expression getDataAuthExpressionByTableName(String tableName, String tableAlias) {
        Expression dataAuthExpression = null;

        List<DataAuthTableRelation> dataAuthTableRelations = redisUtil.get(GlobalConstant.DATA_AUTH_TABLE_RELATION_CACHE_KEY, new TypeReference<List<DataAuthTableRelation>>() {
        });

        //是否有设置权限
        if (CollectionUtil.isEmpty(dataAuthTableRelations) || dataAuthTableRelations.stream().noneMatch(x -> x.getTableName().equals(tableName))) {
            return null;
        }

        //找到当前表所关联的 数据权限
        List<DataAuthTableRelation> tableDataAuths = dataAuthTableRelations.stream().filter(x -> x.getTableName().equals(tableName)).collect(Collectors.toList());

        List<Long> allDataAuthId = tableDataAuths.stream().map(DataAuthTableRelation::getDataAuthId).collect(Collectors.toList());
        List<DataAuth> dataAuths = redisUtil.get(GlobalConstant.DATA_AUTH_CACHE_KEY, new TypeReference<List<DataAuth>>() {
        });

        List<DataAuth> thisTableAuthDataList = dataAuths.stream().filter(x -> allDataAuthId.contains(x.getId())).collect(Collectors.toList());

        List<DataAuthRelation> authRelationList = redisUtil.get(GlobalConstant.DATA_AUTH_RELATION_CACHE_KEY, new TypeReference<List<DataAuthRelation>>() {
        });

        List<DataAuthConfig> authConfigList = redisUtil.get(GlobalConstant.DATA_AUTH_CONFIG_CACHE_KEY, new TypeReference<List<DataAuthConfig>>() {
        });

        for (DataAuth dataAuth : thisTableAuthDataList) {
            Expression expression = null;
            List<Long> userIds = new ArrayList<>();
            //如果是用户权限
            if (dataAuth.getAuthType() == DataAuthTypeEnum.USER.getCode()) {
                //找出有那些用户被赋值了 此数据权限
                userIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());
            } else {
                List<Long> roleIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());

                List<Long> currentRoleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());

                //如果当前登陆人不包含 这些 角色id  默认不添加数据权限
                if (currentRoleIdList.stream().noneMatch(roleIds::contains)) {
                    continue;
                }
                userIds.add(StpUtil.getLoginIdAsLong());
            }
            //判断当前用户是否包含此数据权限
            if (userIds.contains(StpUtil.getLoginIdAsLong())) {

                //如果是简易模式
                if (dataAuth.getAuthMethod() == DataAuthMethodEnum.SIMPLE.getCode()) {
                    //所有能查看的用户数据
                    List<Long> dataAuthSimpleUserId = getDataAuthSimpleUserId(dataAuth.getAuthScope());

                    List<Expression> expressionList = new ArrayList<>();
                    for (Long aLong : dataAuthSimpleUserId) {
                        expressionList.add(new LongValue(aLong));
                    }

                    InExpression inExpression = new InExpression();
                    inExpression.setLeftExpression(buildColumn(tableAlias, GlobalConstant.AUTH_USER_ID));
                    inExpression.setRightItemsList(new ExpressionList(expressionList));

                    expression = inExpression;

                }
                //如果是自定义模式
                else {
                    List<DataAuthConfig> thisDataAuthConfig = authConfigList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).collect(Collectors.toList());
                    expression = getDataAuthCustomExpression(thisDataAuthConfig, dataAuth, tableAlias);
                }
                // 组装数据权限，取并集，用or连接
                if (dataAuthExpression == null) {
                    dataAuthExpression = expression;
                } else {
                    dataAuthExpression = new OrExpression(dataAuthExpression, new Parenthesis(expression));
                }
            }
        }

        return dataAuthExpression;
    }

    /**
     * 自定义模式 根据数据权限 获取 Expression
     *
     * @return
     */
    @SneakyThrows
    public static Expression getDataAuthCustomExpression(List<DataAuthConfig> configs, DataAuth dataAuth, String tableAlias) {
        Expression dataAuthExpression = null;

        if (StrUtil.isNotBlank(dataAuth.getAuthFormula())) {

            StringBuilder resultExpresionString = new StringBuilder();
            String[] split = dataAuth.getAuthFormula().split("");

            for (String str : split) {
                //如果是数字 并且  包含当前
                if(StrUtil.isNumeric(str)){
                    Integer order = Convert.toInt(str);

                    Optional<DataAuthConfig> configOptional = configs.stream().filter(x -> ObjectUtil.equals(x.getOrderNumber(), order)).findFirst();
                    if (!configOptional.isPresent()) {
                        continue;
                    }
                    Expression expression = getExpression(tableAlias, configOptional.get());
                    resultExpresionString.append(expression);
                }
                else {
                    resultExpresionString.append(str);
                }
            }

            dataAuthExpression = CCJSqlParserUtil.parseExpression(resultExpresionString.toString());
        }


//        if (StrUtil.isNotBlank(dataAuth.getAuthFormula())) {
//            String OrString = "or";
//            String AndString = "and";
//            //首先根据 or  切割 字符串
//            String[] ors = dataAuth.getAuthFormula().toLowerCase().split(OrString);
//
//            for (int i = 0; i < ors.length; i++) {
//                //去除左右括号 再根据 and 切割
//                String[] condition = ors[i].replace(StringPool.LEFT_BRACKET,StringPool.EMPTY).replace(StringPool.RIGHT_BRACKET,StringPool.EMPTY).toLowerCase().split(AndString);
//                Expression expression = null;
//                for (String index : condition) {
//                    Optional<DataAuthConfig> configOptional = configs.stream().filter(x -> ObjectUtil.equals(x.getOrderNumber(), Integer.valueOf(index.trim()))).findFirst();
//
//                    if (!configOptional.isPresent()) {
//                        continue;
//                    }
//                    expression = getExpression(tableAlias, expression, configOptional.get());
//                }
//                //如果是最后一个 不再需要拼接or
//                if(i != ors.length - 1){
//                    //如果是第一个条件 直接赋值
//                    if(ObjectUtil.isNull(dataAuthExpression)){
//                        dataAuthExpression = new Parenthesis(expression);
//                    }
//                    else {
//                        dataAuthExpression = new OrExpression(dataAuthExpression, new Parenthesis(expression));
//                    }
//                }
//                else {
//                    dataAuthExpression = new AndExpression(dataAuthExpression,new Parenthesis(expression));
//                }
////                //如果有括号
////                if (ors[i].contains(StringPool.LEFT_BRACKET) && ors[i].contains(StringPool.RIGHT_BRACKET)) {
////
////                }
////
//
//            }
//
////            for (String or : ors) {
////                //如果有括号
////                if (or.contains(StringPool.LEFT_BRACKET) && or.contains(StringPool.RIGHT_BRACKET)) {
////                    //去除左右括号 再根据 and 切割
////                    String[] condition = or.replace(StringPool.LEFT_BRACKET,StringPool.EMPTY).replace(StringPool.LEFT_BRACKET,StringPool.EMPTY).toLowerCase().split(AndString);
////                    Expression expression = null;
////                    for (String index : condition) {
////                        Optional<DataAuthConfig> configOptional = configs.stream().filter(x -> ObjectUtil.equals(x.getOrderNumber(), Integer.valueOf(index))).findFirst();
////
////                        if (!configOptional.isPresent()) {
////                            continue;
////                        }
////                        expression = getExpression(tableAlias, expression, configOptional.get());
////                    }
////
////                    dataAuthExpression = new Parenthesis(dataAuthExpression);
////                }
////
////
////            }
//        }
        else {
            for (DataAuthConfig config : configs) {
                dataAuthExpression = getExpression(tableAlias, dataAuthExpression, config);
            }
        }

        return dataAuthExpression;
    }

    /**
     * 拼接所有的权限表达式
     * @param tableAlias
     * @param dataAuthExpression
     * @param config
     * @return
     */
    private static Expression getExpression(String tableAlias, Expression dataAuthExpression, DataAuthConfig config) {
        if (config.getFieldType() == DataAuthFieldTypeEnum.STRING.getCode()) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            equalsTo.setRightExpression(new StringValue(config.getFieldValue()));

            //如果是第一个条件 直接赋值
            if (ObjectUtil.isNull(dataAuthExpression)) {
                dataAuthExpression = equalsTo;
            } else {
                dataAuthExpression = new AndExpression(dataAuthExpression, equalsTo);
            }
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.INT.getCode()) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            equalsTo.setRightExpression(new LongValue(config.getFieldValue()));
            //如果是第一个条件 直接赋值
            if (ObjectUtil.isNull(dataAuthExpression)) {
                dataAuthExpression = equalsTo;
            } else {
                dataAuthExpression = new AndExpression(dataAuthExpression, equalsTo);
            }
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_USER_ID.getCode()) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            equalsTo.setRightExpression(new LongValue(StpUtil.getLoginIdAsLong()));
            //如果是第一个条件 直接赋值
            if (ObjectUtil.isNull(dataAuthExpression)) {
                dataAuthExpression = equalsTo;
            } else {
                dataAuthExpression = new AndExpression(dataAuthExpression, equalsTo);
            }
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_DEP_ID.getCode()) {
            InExpression inExpression = new InExpression();
            inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            List<Department> departmentList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
            List<Expression> list = new ArrayList<>();
            for (Department department : departmentList) {
                list.add(new LongValue(department.getId()));
            }

            inExpression.setRightItemsList(new ExpressionList(list));
            //如果是第一个条件 直接赋值
            if (ObjectUtil.isNull(dataAuthExpression)) {
                dataAuthExpression = inExpression;
            } else {
                dataAuthExpression = new AndExpression(dataAuthExpression, inExpression);
            }
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_DEP_CHILD_ID.getCode()) {
            InExpression inExpression = new InExpression();
            inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            List<Department> departmentList = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference<List<Department>>() {
            });
            SaSession tokenSession = StpUtil.getTokenSession();
            List<Department> currentDepartmentList = tokenSession.get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
            List<Long> currentDepartmentIdList = currentDepartmentList.stream().map(Department::getId).collect(Collectors.toList());
            List<Long> myAndOrgAndChildOrgUserId = getAllOrgChildId(ListUtil.toList(currentDepartmentIdList), departmentList);
            myAndOrgAndChildOrgUserId.addAll(currentDepartmentIdList);
            List<Expression> list = new ArrayList<>();
            for (Long id : myAndOrgAndChildOrgUserId) {
                list.add(new LongValue(id));
            }

            inExpression.setRightItemsList(new ExpressionList(list));
            //如果是第一个条件 直接赋值
            if (ObjectUtil.isNull(dataAuthExpression)) {
                dataAuthExpression = inExpression;
            } else {
                dataAuthExpression = new AndExpression(dataAuthExpression, inExpression);
            }
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_USER_NAME.getCode()) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
            equalsTo.setRightExpression(new StringValue(user.getUserName()));
            //如果是第一个条件 直接赋值
            if (ObjectUtil.isNull(dataAuthExpression)) {
                dataAuthExpression = equalsTo;
            } else {
                dataAuthExpression = new AndExpression(dataAuthExpression, equalsTo);
            }
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_POST_ID.getCode()) {
            InExpression inExpression = new InExpression();
            inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            List<Post> postList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_POST_LIST_KEY, new ArrayList<>());
            List<Expression> list = new ArrayList<>();
            for (Post post : postList) {
                list.add(new LongValue(post.getId()));
            }
            inExpression.setRightItemsList(new ExpressionList(list));
            //如果是第一个条件 直接赋值
            if (ObjectUtil.isNull(dataAuthExpression)) {
                dataAuthExpression = inExpression;
            } else {
                dataAuthExpression = new AndExpression(dataAuthExpression, inExpression);
            }
        } else {
            InExpression inExpression = new InExpression();
            inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            List<Long> roleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
            List<Expression> list = new ArrayList<>();
            for (Long id : roleIdList) {
                list.add(new LongValue(id));
            }
            inExpression.setRightItemsList(new ExpressionList(list));
            //如果是第一个条件 直接赋值
            if (ObjectUtil.isNull(dataAuthExpression)) {
                dataAuthExpression = inExpression;
            } else {
                dataAuthExpression = new AndExpression(dataAuthExpression, inExpression);
            }
        }
        return dataAuthExpression;
    }

    /**
     * 只返回一个权限表达式
     * @param tableAlias
     * @param config
     * @return
     */
    private static Expression getExpression(String tableAlias, DataAuthConfig config) {
        Integer conditionType = config.getConditionType();
        if (config.getFieldType() == DataAuthFieldTypeEnum.STRING.getCode()) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            equalsTo.setRightExpression(new StringValue(config.getFieldValue()));
            return equalsTo;
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.INT.getCode()) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            equalsTo.setRightExpression(new LongValue(config.getFieldValue()));
            return equalsTo;
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_USER_ID.getCode()) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            equalsTo.setRightExpression(new LongValue(StpUtil.getLoginIdAsLong()));
            return equalsTo;
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_DEP_ID.getCode()) {
            InExpression inExpression = new InExpression();
            inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            List<Department> departmentList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
            List<Expression> list = new ArrayList<>();
            for (Department department : departmentList) {
                list.add(new LongValue(department.getId()));
            }

            inExpression.setRightItemsList(new ExpressionList(list));
            return inExpression;
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_DEP_CHILD_ID.getCode()) {
            InExpression inExpression = new InExpression();
            inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            List<Department> departmentList = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference<List<Department>>() {
            });
            SaSession tokenSession = StpUtil.getTokenSession();
            List<Department> currentDepartmentList = tokenSession.get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
            List<Long> currentDepartmentIdList = currentDepartmentList.stream().map(Department::getId).collect(Collectors.toList());
            List<Long> myAndOrgAndChildOrgUserId = getAllOrgChildId(currentDepartmentIdList, departmentList);
            myAndOrgAndChildOrgUserId.addAll(currentDepartmentIdList);
            List<Expression> list = new ArrayList<>();
            for (Long id : myAndOrgAndChildOrgUserId) {
                list.add(new LongValue(id));
            }

            inExpression.setRightItemsList(new ExpressionList(list));
            //如果是第一个条件 直接赋值
            return inExpression;
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_USER_NAME.getCode()) {
            EqualsTo equalsTo = new EqualsTo();
            equalsTo.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            User user = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
            equalsTo.setRightExpression(new StringValue(user.getUserName()));
            return equalsTo;
        } else if (config.getFieldType() == DataAuthFieldTypeEnum.LOGIN_POST_ID.getCode()) {
            InExpression inExpression = new InExpression();
            inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            List<Post> postList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_POST_LIST_KEY, new ArrayList<>());
            List<Expression> list = new ArrayList<>();
            for (Post post : postList) {
                list.add(new LongValue(post.getId()));
            }
            inExpression.setRightItemsList(new ExpressionList(list));
            return inExpression;
        } else {
            InExpression inExpression = new InExpression();
            inExpression.setLeftExpression(buildColumn(tableAlias, config.getFieldName()));
            List<Long> roleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
            List<Expression> list = new ArrayList<>();
            for (Long id : roleIdList) {
                list.add(new LongValue(id));
            }
            inExpression.setRightItemsList(new ExpressionList(list));
            return inExpression;
        }
    }


    /**
     * 构建Column
     *
     * @param tableAlias 表别名
     * @param columnName 字段名称
     * @return 带表别名字段
     */
    public static Column buildColumn(String tableAlias, String columnName) {
        if (StrUtil.isNotEmpty(tableAlias)) {
            columnName = tableAlias + StringPool.DOT + columnName;
        }
        return new Column(columnName);
    }

    public static List<Long> getDataAuthByTableName(String tableName) {

        List<Long> result = new ArrayList<>();

        List<DataAuthTableRelation> dataAuthTableRelations = redisUtil.get(GlobalConstant.DATA_AUTH_TABLE_RELATION_CACHE_KEY, new TypeReference<List<DataAuthTableRelation>>() {
        });

        //是否有设置权限
        if (dataAuthTableRelations.stream().noneMatch(x -> x.getTableName().equals(tableName))) {
            return result;
        }

        //找到当前表所关联的 数据权限
        List<DataAuthTableRelation> tableDataAuths = dataAuthTableRelations.stream().filter(x -> x.getTableName().equals(tableName)).collect(Collectors.toList());

        List<Long> allDataAuthId = tableDataAuths.stream().map(DataAuthTableRelation::getDataAuthId).collect(Collectors.toList());
        List<DataAuth> dataAuths = redisUtil.get(GlobalConstant.DATA_AUTH_CACHE_KEY, new TypeReference<List<DataAuth>>() {
        });

        List<DataAuth> thisTableAuthDataList = dataAuths.stream().filter(x -> allDataAuthId.contains(x.getId())).collect(Collectors.toList());

        List<DataAuthRelation> authRelationList = redisUtil.get(GlobalConstant.DATA_AUTH_RELATION_CACHE_KEY, new TypeReference<List<DataAuthRelation>>() {
        });

        for (DataAuth dataAuth : thisTableAuthDataList) {
            //如果是用户权限
            if (dataAuth.getAuthType() == DataAuthTypeEnum.USER.getCode()) {
                //找出有那些用户被赋值了 此数据权限
                List<Long> userIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());

                //判断当前用户是否包含此数据权限
                if (userIds.contains(StpUtil.getLoginIdAsLong())) {

                    //如果是简易模式
                    if (dataAuth.getAuthMethod() == DataAuthMethodEnum.CUSTOM.getCode()) {
                        List<Long> dataAuthSimpleUserId = getDataAuthSimpleUserId(dataAuth.getAuthScope());
                        result.addAll(dataAuthSimpleUserId);
                    }
                    //如果是自定义模式
                    else {

                    }

                }
            }
        }

        return result;
    }

    /**
     * 获取简易模式的所有用户id
     *
     * @return
     */
    private static List<Long> getDataAuthSimpleUserId(Integer authScope) {
        DataAuthScopeEnum enumAt = EnumUtil.getEnumAt(DataAuthScopeEnum.class, authScope);
        switch (enumAt) {
            case MY:
                return ListUtil.toList(StpUtil.getLoginIdAsLong());
            case MY_AND_POST:
                return getMyAndPostUserId();
            case MY_AND_CHILD_POST:
                return getMyAndChildPostUserId();
            case MY_AND_POST_AND_CHILD_POST:
                return getMyAndPostAndChildPostUserId();
            case MY_AND_ORG:
                return getMyAndOrgUserId();
            case MY_AND_CHILD_ORG:
                return getMyAndChildOrgUserId();
            case MY_AND_ORG_AND_CHILD_ORG:
                return getMyAndOrgAndChildOrgUserId();
            default:
                return getRoleUserId();
        }
    }

    /**
     * 获取同岗位的用户id
     *
     * @return
     */
    private static List<Long> getMyAndPostUserId() {
        List<UserPostRelation> userRelationList = redisUtil.get(GlobalConstant.USER_POST_RELATION_CACHE_KEY, new TypeReference<List<UserPostRelation>>() {
        });
        SaSession tokenSession = StpUtil.getTokenSession();
        List<Post> postList = tokenSession.get(GlobalConstant.LOGIN_USER_POST_LIST_KEY, new ArrayList<>(0));
        List<Long> postIdList = postList.stream().map(Post::getId).collect(Collectors.toList());

        return userRelationList.stream()
                .filter(x -> postIdList.contains(x.getPostId()))
                .map(UserPostRelation::getUserId).collect(Collectors.toList());
    }

    /**
     * 获取同岗位的用户id
     *
     * @return
     */
    private static List<Long> getMyAndChildPostUserId() {
        List<UserPostRelation> userRelationList = redisUtil.get(GlobalConstant.USER_POST_RELATION_CACHE_KEY, new TypeReference<List<UserPostRelation>>() {
        });

        List<Post> postList = redisUtil.get(GlobalConstant.POST_CACHE_KEY, new TypeReference<List<Post>>() {
        });
        SaSession tokenSession = StpUtil.getTokenSession();
        List<Post> currentPostList = tokenSession.get(GlobalConstant.LOGIN_USER_POST_LIST_KEY, new ArrayList<>(0));
        List<Long> postIdList = currentPostList.stream().map(Post::getId).collect(Collectors.toList());

        List<Long> resultList = new ArrayList<>();
        //如果有下级  则使用递归 找到所有下级post  求出所有用户id
        if (postList.stream().anyMatch(x -> postIdList.contains(x.getParentId()))) {
            List<Long> allPostId = getAllPostChildId(postIdList, postList);
            resultList.addAll(userRelationList.stream().filter(user -> allPostId.contains(user.getPostId())).map(UserPostRelation::getUserId).collect(Collectors.toList()));
        }

        //当前登录人id
        resultList.add(StpUtil.getLoginIdAsLong());
        return resultList;
    }

    private static List<Long> getMyAndPostAndChildPostUserId() {
        List<Long> result = new ArrayList<>();
        result.addAll(getMyAndPostUserId());
        result.addAll(getMyAndChildPostUserId());
        return result;
    }

    private static List<Long> getAllPostChildId(List<Long> postIds, List<Post> postList) {
        List<Long> resultList = new ArrayList<>();
        for (Long postId : postIds) {
            for (Post post : postList) {
                if (postId.equals(post.getParentId())) {
                    resultList.add(post.getId());
                }
            }
        }
        if (CollectionUtils.isNotEmpty(resultList)) {
            resultList.addAll(getAllPostChildId(resultList, postList));
        }
        return resultList;

    }

    private static List<Long> getAllOrgChildId(List<Long> depIds, List<Department> departmentList) {
        List<Long> resultList = new ArrayList<>();
        for (Long depId : depIds) {
            for (Department department : departmentList) {
                if (depId.equals(department.getParentId())) {
                    resultList.add(department.getId());
                }
            }
        }
        if (CollectionUtils.isNotEmpty(resultList)) {
            resultList.addAll(getAllOrgChildId(resultList, departmentList));
        }
        return resultList;

    }

    /**
     * 获取同机构/部门的数据
     *
     * @return
     */
    public static List<Long> getMyAndOrgUserId() {
        List<UserDeptRelation> userDeptRelations = redisUtil.get(GlobalConstant.USER_DEPT_RELATION_CACHE_KEY, new TypeReference<List<UserDeptRelation>>() {
        });
        SaSession tokenSession = StpUtil.getTokenSession();
        List<Department> departmentList = tokenSession.get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
        List<Long> departmentIdList = departmentList.stream().map(Department::getId).collect(Collectors.toList());

        return userDeptRelations.stream()
                .filter(x -> departmentIdList.contains(x.getDeptId()))
                .map(UserDeptRelation::getUserId).collect(Collectors.toList());
    }

    /**
     * 获取下属机构数据的用户id
     *
     * @return
     */
    private static List<Long> getMyAndChildOrgUserId() {
        List<Long> resultList = new ArrayList<>();
        List<UserDeptRelation> userDeptRelations = redisUtil.get(GlobalConstant.USER_DEPT_RELATION_CACHE_KEY, new TypeReference<List<UserDeptRelation>>() {
        });

        List<Department> departmentList = redisUtil.get(GlobalConstant.DEP_CACHE_KEY, new TypeReference<List<Department>>() {
        });
        SaSession tokenSession = StpUtil.getTokenSession();
        List<Department> currentDepartmentList = tokenSession.get(GlobalConstant.LOGIN_USER_DEPT_LIST_KEY, new ArrayList<>(0));
        List<Long> currentDepartmentIdList = currentDepartmentList.stream().map(Department::getId).collect(Collectors.toList());

        //如果有下级  则使用递归 找到所有下级post  求出所有用户id
        if (departmentList.stream().anyMatch(x -> currentDepartmentIdList.contains(x.getParentId()))) {
            List<Long> allChildIdList = getAllOrgChildId(currentDepartmentIdList, departmentList);
            resultList.addAll(userDeptRelations.stream().filter(user -> allChildIdList.contains(user.getDeptId())).map(UserDeptRelation::getUserId).collect(Collectors.toList()));
        }

        //如果没有下级  直接使用当前登陆人岗位
        resultList.add(StpUtil.getLoginIdAsLong());
        return resultList;
    }

    /**
     * 获取当前机构 和下属机构
     *
     * @return
     */
    private static List<Long> getMyAndOrgAndChildOrgUserId() {
        List<Long> result = new ArrayList<>();
        result.addAll(getMyAndOrgUserId());
        result.addAll(getMyAndChildOrgUserId());
        return result;
    }

    /**
     * 获取同角色
     *
     * @return
     */
    private static List<Long> getRoleUserId() {
        List<UserRoleRelation> userRoleRelationList = redisUtil.get(GlobalConstant.USER_ROLE_RELATION_CACHE_KEY, new TypeReference<List<UserRoleRelation>>() {
        });


        List<Long> roleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());


        return userRoleRelationList.stream().filter(r -> roleIdList.contains(r.getRoleId())).map(UserRoleRelation::getUserId).collect(Collectors.toList());
    }


    /**
     * 根据 tableName 生成 expression 给自定义表单 生成sql
     *
     * @param tableName  表名
     * @return
     */
//    public static Expression getDataAuthEntityByTableName(String tableName) {
//        SelectUtils.buildSelectFromTable(new Table(tableName));
//
//        List<DataAuthTableRelation> dataAuthTableRelations = redisUtil.get(GlobalConstant.DATA_AUTH_TABLE_RELATION_CACHE_KEY, new TypeReference<List<DataAuthTableRelation>>() {
//        });
//
//        //是否有设置权限
//        if (dataAuthTableRelations.stream().noneMatch(x -> x.getTableName().equals(tableName))) {
//            return where;
//        }
//
//        //找到当前表所关联的 数据权限
//        List<DataAuthTableRelation> tableDataAuths = dataAuthTableRelations.stream().filter(x -> x.getTableName().equals(tableName)).collect(Collectors.toList());
//
//        List<Long> allDataAuthId = tableDataAuths.stream().map(DataAuthTableRelation::getDataAuthId).collect(Collectors.toList());
//        List<DataAuth> dataAuths = redisUtil.get(GlobalConstant.DATA_AUTH_CACHE_KEY, new TypeReference<List<DataAuth>>() {
//        });
//
//        List<DataAuth> thisTableAuthDataList = dataAuths.stream().filter(x -> allDataAuthId.contains(x.getId())).collect(Collectors.toList());
//
//        List<DataAuthRelation> authRelationList = redisUtil.get(GlobalConstant.DATA_AUTH_RELATION_CACHE_KEY, new TypeReference<List<DataAuthRelation>>() {
//        });
//
//        List<DataAuthConfig> authConfigList = redisUtil.get(GlobalConstant.DATA_AUTH_CONFIG_CACHE_KEY, new TypeReference<List<DataAuthConfig>>() {
//        });
//
//        for (DataAuth dataAuth : thisTableAuthDataList) {
//            List<Long> userIds = new ArrayList<>();
//            //如果是用户权限
//            if (dataAuth.getAuthType() == DataAuthTypeEnum.USER.getCode()) {
//                //找出有那些用户被赋值了 此数据权限
//                userIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());
//            } else {
//                List<Long> roleIds = authRelationList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).map(DataAuthRelation::getObjectId).collect(Collectors.toList());
//
//                List<Role> roleList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_INFO_KEY, new ArrayList<>());
//
//                //如果当前登陆人不包含 这些 角色id  默认不添加数据权限
//                if (roleList.stream().map(Role::getId).noneMatch(roleIds::contains)) {
//                    continue;
//                }
//            }
//            //判断当前用户是否包含此数据权限
//            if (userIds.contains(StpUtil.getLoginIdAsLong())) {
//
//                //如果是简易模式
//                if (dataAuth.getAuthMethod() == DataAuthMethodEnum.SIMPLE.getCode()) {
//                    //所有能查看的用户数据
//                    List<Long> dataAuthSimpleUserId = getDataAuthSimpleUserId(dataAuth.getAuthScope());
//
////                    where.set(GlobalConstant.AUTH_USER_ID,  new Condition(GlobalConstant.AUTH_USER_ID, "in", dataAuthSimpleUserId));
//                    where.set(GlobalConstant.AUTH_USER_ID,  dataAuthSimpleUserId);
//
//                }
//                //如果是自定义模式
//                else {
//                    List<DataAuthConfig> thisDataAuthConfig = authConfigList.stream().filter(x -> x.getDataAuthId().equals(dataAuth.getId())).collect(Collectors.toList());
//                }
//
//            }
//        }
//
//        return where;
//    }

}
